package com.wengzw.gateway.config;

import com.wengzw.gateway.filter.JwtTokenAuthenticationFilter;
import com.wengzw.gateway.handler.AuthenticationFailHandler;
import com.wengzw.gateway.handler.AuthenticationSuccessHandler;
import com.wengzw.gateway.handler.CustomHttpBasicServerAuthenticationEntryPoint;
import com.wengzw.gateway.handler.TimingLogoutSuccessHandler;
import com.wengzw.gateway.service.SecurityUserDetailService;
import com.wengzw.gateway.utils.MyPasswordEncoder;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.buffer.DefaultDataBufferFactory;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.ReactiveAuthenticationManager;
import org.springframework.security.authentication.UserDetailsRepositoryReactiveAuthenticationManager;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.security.web.server.context.NoOpServerSecurityContextRepository;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;

@EnableWebFluxSecurity
public class SecurityConfig {

    @Resource
    private MyPasswordEncoder myPasswordEncoder;
    @Resource
    private CustomHttpBasicServerAuthenticationEntryPoint customHttpBasicServerAuthenticationEntryPoint;
    @Resource
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @Resource
    private AuthenticationFailHandler authenticationFailHandler;
    @Resource
    private TimingLogoutSuccessHandler timingLogoutSuccessHandler;
    @Resource
    private JwtTokenAuthenticationFilter jwtTokenAuthenticationFilter;

    private static final String[] excludeAuthPages = {
            "/auth/**",
            "/blooduser/user/register",
            "/bloodAdmin/**",
            "/bloodAdmin/admin/info/**",
            "/bloodPoster/poster/getposters/**",
            "/BloodStocks/stocks/**",
            "/bloodOpinion/opinion/**",
            "/bloodNotice/notice/**",
            "/bloodPoster/poster/getPostersById/**",
            "/bloodPoster/poster/admin/**",
            "/common/**",     //上传下载
            "/bloodKnow/**", //献血知识库
            "/blooduser/user/countRegister/**", //统计人数
            "/bloodPoster/poster/countPoster/**",
            "/staservice/**",  //图表显示
            "/bloodAdmin/admin/user/**",
            "/bloodmsm/msm/**"
    };

    // 实现该处的ReactiveUserDetailsService
    @Bean
    public ReactiveAuthenticationManager reactiveAuthenticationManager(SecurityUserDetailService userDetailsService) {
        UserDetailsRepositoryReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
        authenticationManager.setPasswordEncoder(myPasswordEncoder);
        return authenticationManager;
    }

    @Bean
    public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http,
                                                         ReactiveAuthenticationManager reactiveAuthenticationManager) {
        System.out.println("访问 ReactiveAuthenticationManager  。。。。。。。。。。。");
        http.csrf(ServerHttpSecurity.CsrfSpec::disable)
                .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
                .authenticationManager(reactiveAuthenticationManager)
                .exceptionHandling()
                .authenticationEntryPoint(customHttpBasicServerAuthenticationEntryPoint)// 自定义authenticationEntryPoint
                .accessDeniedHandler((swe, e) -> {
                    swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                    return swe.getResponse().writeWith(Mono.just(new DefaultDataBufferFactory().wrap("FORBIDDEN".getBytes())));
                })
                .and()
                .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
                .authorizeExchange()
                .pathMatchers(excludeAuthPages).permitAll()// 白名单
                .pathMatchers(HttpMethod.OPTIONS).permitAll()// option请求默认放行
                .anyExchange()
                .authenticated()
                .and()
                .formLogin().loginPage("/auth/login")
                .authenticationSuccessHandler(authenticationSuccessHandler)// 自定义authenticationSuccessHandler
                .authenticationFailureHandler(authenticationFailHandler)// 自定义authenticationFailureHandler
                .and()
                .logout().logoutUrl("/auth/logout")
                .logoutSuccessHandler(timingLogoutSuccessHandler)// 自定义logoutSuccessHandler
                .and()
                .addFilterAt(jwtTokenAuthenticationFilter, SecurityWebFiltersOrder.HTTP_BASIC);
        return http.build();
    }
}
